package javabase.demo03;

import java.util.concurrent.atomic.*;

public class AtomicPractice {

    private static AtomicInteger atomicCount = new AtomicInteger(0);
    private static int normalCount = 0;

    public static void main(String[] args) throws InterruptedException{
        // 1. 基本原子类使用
        demonstrateBasicAtomic();

        // 2. CAS原理演示
        demonstrateCAS();

        // 3. ABA问题演示
        demonstrateABAProblem();

        // 4. 其他原子类
        demonstrateOtherAtomicClasses();

    }

    private static void demonstrateBasicAtomic() throws InterruptedException {
        System.out.println("\n=== 基本原子类使用 ===");

        // 使用原子类解决计数问题
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                atomicCount.incrementAndGet(); // 原子操作
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                atomicCount.incrementAndGet(); // 原子操作
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("原子计数: " + atomicCount.get());

        // 对比普通变量
        normalCount = 0;
        t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                normalCount++; // 非原子操作
            }
        });

        t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                normalCount++; // 非原子操作
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("普通计数: " + normalCount);

        // 其他原子操作
        System.out.println("当前值: " + atomicCount.get());
        System.out.println("增加10后: " + atomicCount.addAndGet(10));
        System.out.println("比较并设置(期望20，设置30): " +
                atomicCount.compareAndSet(20, 30) + ", 当前值: " + atomicCount.get());

    }

    private static void demonstrateCAS() {
        System.out.println("\n=== CAS原理演示 ===");

        // 模拟CAS操作
        int expected = atomicCount.get();
        int newValue = expected + 5;

        while (true) {
            int current = atomicCount.get();
            if (atomicCount.compareAndSet(current, current + 5)) {
                System.out.println("CAS成功: " + current + " -> " + (current + 5));
                break;
            } else {
                System.out.println("CAS失败，重试");
            }
        }
    }

    private static void demonstrateABAProblem() {
        System.out.println("\n=== ABA问题演示 ===");

        AtomicInteger value = new AtomicInteger(10);

        // 线程1：A->B->A
        Thread t1 = new Thread(() -> {
            System.out.println("线程1: A->B " + value.compareAndSet(10, 20));
            System.out.println("线程1: B->A " + value.compareAndSet(20, 10));
        });

        // 线程2：检查A，但期间值可能经历了A->B->A的变化
        Thread t2 = new Thread(() -> {
            try {
                Thread.sleep(100); // 确保线程1先执行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            boolean success = value.compareAndSet(10, 30);
            System.out.println("线程2: A->30 " + success + ", 最终值: " + value.get());
        });

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 使用AtomicStampedReference解决ABA问题
        System.out.println("\n使用AtomicStampedReference解决ABA问题:");

        AtomicStampedReference<Integer> stampedRef = new AtomicStampedReference<>(10, 0);

        t1 = new Thread(() -> {
            int stamp = stampedRef.getStamp();
            System.out.println("线程1: A->B " +
                    stampedRef.compareAndSet(10, 20, stamp, stamp + 1));
            stamp = stampedRef.getStamp();
            System.out.println("线程1: B->A " +
                    stampedRef.compareAndSet(20, 10, stamp, stamp + 1));
        });

        t2 = new Thread(() -> {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            int stamp = stampedRef.getStamp();
            boolean success = stampedRef.compareAndSet(10, 30, stamp, stamp + 1);
            System.out.println("线程2: A->30 " + success +
                    ", 最终值: " + stampedRef.getReference() +
                    ", 版本: " + stampedRef.getStamp());
        });

        t1.start();
        t2.start();
    }

    private static void demonstrateOtherAtomicClasses() {
        System.out.println("\n=== 其他原子类 ===");

        // AtomicLong
        AtomicLong atomicLong = new AtomicLong(100L);
        System.out.println("AtomicLong: " + atomicLong.getAndAdd(10));

        // AtomicBoolean
        AtomicBoolean atomicBoolean = new AtomicBoolean(true);
        System.out.println("AtomicBoolean: " + atomicBoolean.compareAndSet(true, false));

        // AtomicReference
        AtomicReference<String> atomicReference = new AtomicReference<>("Hello");
        System.out.println("AtomicReference: " +
                atomicReference.compareAndSet("Hello", "World"));
        System.out.println("当前值: " + atomicReference.get());

        // AtomicIntegerArray
        int[] array = {1, 2, 3};
        AtomicIntegerArray atomicArray = new AtomicIntegerArray(array);
        atomicArray.compareAndSet(1, 2, 20);
        System.out.println("AtomicIntegerArray: " + atomicArray.toString());

        // AtomicIntegerFieldUpdater
        class Data {
            volatile int value;
        }

        Data data = new Data();
        AtomicIntegerFieldUpdater<Data> updater =
                AtomicIntegerFieldUpdater.newUpdater(Data.class, "value");

        updater.set(data, 100);
        System.out.println("AtomicIntegerFieldUpdater: " + updater.get(data));
    }
}
